/**
 * 
 */
package org.ndx.jsg.output.freemarker;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.tika.metadata.Metadata;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.ndx.jsg.FileInfos;
import org.ndx.jsg.RelativePathProvider;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class FileWritingInfos implements Comparable<FileWritingInfos> {
	private static final Logger logger = Logger
			.getLogger(FileWritingInfos.class.getName());

	private final FileInfos infos;

	private Date writingDate;

	private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";

	private static final DateFormat format = new SimpleDateFormat(DATE_FORMAT);

	public final String name;

	private Map<String, String> templateMappings = new TreeMap<String, String>();

	private final NameResolver resolver;

	public FileWritingInfos(FileInfos fileInfos, NameResolver resolver) {
		this.infos = fileInfos;
		this.name = fileInfos.getRelativePath();
		this.resolver = resolver;
		try {
			String date = infos.getMetadata().get(Metadata.DATE);
			this.writingDate = format.parse(date);
		} catch (Exception e) {
			logger.log(Level.FINE, "a date was unparsable", e);
			this.writingDate = new Date();
		}
	}

	public String getName() {
		return name;
	}

	/**
	 * Get string from template name
	 * 
	 * @param templateName
	 * @return name of file associated to template name
	 */
	public String getUrl(String templateName) {
		return resolver.resolve(infos, templateName, true);
	}

	/**
	 * Get url associated to file by applying the given template name from the
	 * given relative path.
	 * 
	 * @param relativePath
	 *            a path separated using {@link File#separator}. Notice it must
	 *            be a path to a file, not a path to a directory
	 * @param templateName
	 *            a template name corresponding to
	 *            {@link TemplateApplier#resolveFileName(String, String, String)}
	 * @return the shortest possible relative path
	 */
	public String getUrl(String relativePath, String templateName) {
		String relativeUrl = getUrl(templateName);
		return Utils.compress(relativePath, relativeUrl).replace(
				File.separator, "/");
	}

	public String getMetadata(String name) {
		String metadata = infos.getMetadata().get(name);
		if (metadata == null) {
			return "";
		}
		return metadata;
	}

	public String[] getAllMetadata(String name) {
		String[] metadata = infos.getMetadata().getValues(name);
		if (metadata == null) {
			return new String[0];
		}
		return metadata;
	}

	@Override
	public int compareTo(FileWritingInfos o) {
		return writingDate.compareTo(o.writingDate);
	}

	public Date getWritingDate() {
		return writingDate;
	}

	FileInfos getInfos() {
		return infos;
	}

	/**
	 * Create an object that can be seen as a document by our freemarker
	 * template architecture.
	 * 
	 * @return
	 * @throws ParserConfigurationException
	 * @throws IOException
	 * @throws SAXException
	 */
	public Object getDocument() throws Exception,
			ParserConfigurationException {
		// First, load file as XML (to replace @relocatable links with correct
		// ones)
        SAXReader reader = new SAXReader();
        Document document = reader.read(getInfos().getFile().toURI().toURL());
        // Isn'it faster than the cumbersome file reading ?
        String documentText = document.asXML();
        int relocatorStartIndex, relocatorEndIndex;
        String relocatableStart = "{relocatable:";
    	String relocatableEnd = "}";
		while((relocatorStartIndex = documentText.indexOf(relocatableStart))>=0) {
			relocatorEndIndex = documentText.indexOf(relocatableEnd, relocatorStartIndex);
        	String target = documentText.substring(relocatorStartIndex+relocatableStart.length(), relocatorEndIndex);
        	String replaced =  resolver.resolve(new StringPathProvider(getInfos().getRelativePath()+File.separator+target.trim()), "__filename__.html.template", true);
        	// Due to local contract,a File.separator is always put at start 
        	replaced = replaced.substring(File.separator.length());
        	documentText = documentText.replace(relocatableStart+target+relocatableEnd, replaced);
        }
		return freemarker.ext.dom.NodeModel.parse(new InputSource(new StringReader(documentText)));
	}
	
	private static class StringPathProvider implements RelativePathProvider {
		private String dest;

		public StringPathProvider(String target) {
			dest = target;
		}

		@Override
		public String getRelativePath() {
			return dest;
		}
	}
}